<?php
namespace app\api\controller;

use think\facade\Db;
use think\facade\Request;

class Judge
{
    // Judge0 API配置
    private $judge0_url = 'https://ce.judge0.com/submissions/?base64_encoded=false&wait=true';
    // 如有API Key，可在此添加
    private $judge0_headers = [
        'Content-Type: application/json',
        // 'X-Auth-Token: your_api_key',
    ];

    // 语言映射（可根据需要扩展）
    private $language_map = [
        'c' => 50,
        'cpp' => 54,
        'python3' => 71,
        'java' => 62,
        'javascript' => 63,
    ];

    /**
     * 用户提交代码接口
     * @return \think\response\Json
     */
    public function submit()
    {
        $data = Request::post();
        $user_id = $data['user_id'] ?? null;
        $problem_id = $data['problem_id'] ?? null;
        $language = $data['language'] ?? null;
        $code = $data['code'] ?? null;
        $contest_id = $data['contest_id'] ?? null;

        if (!$user_id || !$problem_id || !$language || !$code) {
            return json(['code' => 400, 'message' => '参数不完整']);
        }
        if (!isset($this->language_map[$language])) {
            return json(['code' => 400, 'message' => '不支持的语言']);
        }
        $language_id = $this->language_map[$language];

        // 插入提交记录，初始状态为0（待判题）
        $submission_id = Db::name('submission')->insertGetId([
            'user_id' => $user_id,
            'problem_id' => $problem_id,
            'language' => $language,
            'code' => $code,
            'status' => 0,
            'runtime' => 0,
            'memory' => 0,
            'error_message' => null,
            'score' => 0,
            'judge_time' => null,
            'create_time' => time(),
            'contest_id' => $contest_id,
        ]);

        // 获取所有测试用例
        $test_cases = Db::name('test_case')->where('problem_id', $problem_id)->select()->toArray();
        $total_cases=count($test_cases);
        if (empty($test_cases)) {
            return json(['code' => 404, 'message' => '没有测试用例']);
        }
        $passed_cases = 0;
        $max_runtime = 0;
        $max_memory = 0;
        $error_message = null;
        $final_status = 2; // 2通过，3答案错误，4编译错误，5运行时错误，6时间超限，7内存超限
        $status_priority = [4, 5, 6, 7, 3, 2]; // 优先级：编译错误>运行时错误>时间超限>内存超限>答案错误>通过
        $status_map = [
            3 => 2, // Accepted -> 2 通过
            4 => 3, // Wrong Answer -> 3 答案错误
            6 => 4, // Compilation Error -> 4 编译错误
            5 => 5, // Runtime Error -> 5 运行时错误
            13 => 6, // Time Limit Exceeded -> 6 时间超限
            17 => 7, // Memory Limit Exceeded -> 7 内存超限
        ];
        $status_count = [2=>0,3=>0,4=>0,5=>0,6=>0,7=>0];
        $first_error_message = null;

        foreach ($test_cases as $case) {
            $payload = [
                'source_code' => $code,
                'language_id' => $language_id,
                'stdin' => $case['input_data'],
                'expected_output' => rtrim($case['output_data']) . "\n",
            ];
            $response = $this->call_judge0($payload);
            $status_id = isset($response['status']['id']) ? $response['status']['id'] : 0;
            $status = $status_map[$status_id] ?? 1;
            $stdout = isset($response['stdout']) ? rtrim($response['stdout']) : '';
            $expected = rtrim($case['output_data']);
            if ($status === 2 && $stdout === $expected) {
                $passed_cases++;
            } else {
                if ($first_error_message === null) {
                    $first_error_message = $response['compile_output'] ?? $response['stderr'] ?? null;
                }
            }
            $runtime = (isset($response['time']) && is_numeric($response['time'])) ? intval($response['time'] * 1000) : 0;
            $max_runtime = max($max_runtime, $runtime);
            $max_memory = max($max_memory, isset($response['memory']) && is_numeric($response['memory']) ? $response['memory'] : 0);
            $status_count[$status] = ($status_count[$status] ?? 0) + 1;
        }

        // 综合判定最终状态，按优先级取最高
        foreach ($status_priority as $pri_status) {
            if ($status_count[$pri_status] > 0) {
                $final_status = $pri_status;
                break;
            }
        }
        $score = intval($passed_cases / $total_cases * 100);
        $judge_time = time();

        // 更新提交记录
        Db::name('submission')->where('id', $submission_id)->update([
            'status' => $final_status,
            'runtime' => $max_runtime,
            'memory' => $max_memory,
            'error_message' => $first_error_message,
            'score' => $score,
            'judge_time' => $judge_time,
        ]);

        return json([
            'code' => 200,
            'message' => '提交成功',
            'data' => [
                'submission_id' => $submission_id,
                'status' => $final_status,
                'runtime' => $max_runtime,
                'memory' => $max_memory,
                'error_message' => $first_error_message,
                'score' => $score,
                'passed_cases' => $passed_cases,
                'total_cases' => $total_cases,
            ]
        ]);
    }

    /**
     * 调用Judge0 API
     */
    private function call_judge0($payload)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->judge0_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->judge0_headers);
        $result = curl_exec($ch);
        curl_close($ch);
        return json_decode($result, true);
    }
} 